package db

import (
	"gim/comm"
	"github.com/garyburd/redigo/redis"
)

//用户好友，黑名单及群组等等关系管理
type Manager struct {
	redis_pool *redis.Pool
}

func NewManager(host string, password string) *Manager{
	manager := &Manager{
		redis_pool : comm.NewRedisPool(host, password),
	}
	return manager
}

//存储用户信息到redis
func (manager *Manager)SaveUser(appid int64, uid int64, username string, avatar string, token string) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	user := &User {
		Appid : appid,
		Uid : uid,
		Username : username,
		Avatar : avatar,
		Token : token,
	}
	
	return user.Save(conn)
}

//获取用户信息
func (manager *Manager)GetUser(appid int64, uid int64) *User {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	user := new(User)
	return user.Get(conn, appid, uid)
}

//添加用户黑名单
func (manager *Manager)AddUserBlack(appid int64, uid int64, bid int64) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	return AddBlack(conn, appid, uid, bid)
}

//判断是否在黑名单列表中
func (manager *Manager)IsUserBlack(appid int64, uid int64, bid int64) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	return IsBlack(conn, appid, uid, bid)
}

//获取用户黑名单列表
func (manager *Manager)GetUserBlacks(appid int64, uid int64) []*User {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	uids := GetBlacks(conn, appid, uid)
	
	c := make([]*User, 0, 10)
	for _, uid := range uids {
		u := manager.GetUser(appid, int64(uid));
		
		if u == nil {
			continue
		}
		
		c = append(c, u)
	}
	
	return c
}

//从黑名单移除
func (manager *Manager)RemoveUserBlack(appid int64, uid int64, bid int64) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	return RemoveBlack(conn, appid, uid, bid)
}

//存储群信息，必须有群主信息
func (manager *Manager)SaveGroup(appid int64, owner int64, name string, avatar string, desc string) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	group := &Group{
		Appid : appid,
		Name  : name,
		Avatar: avatar,
		Desc  : desc,
		Owner : owner,
	}
	
	if(!group.Save(conn)){
		return false
	}
	
	//将群主加入到群成员
	AddMember(conn, appid, group.Gid, group.Owner)
	
	//将群加入到群主群列表
	AddGroup(conn, appid, owner, group.Gid)
	
	return true
}

//获取群组信息
func (manager *Manager)GetGroup(appid int64, gid int64) *Group {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	group := new(Group)
	
	return group.Get(conn, appid, gid)
}

//加人进群组
func (manager *Manager)AddToGroup(appid int64, gid int64, uid int64) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	//加人进群成员列表
	if !AddMember(conn, appid, gid, uid) {
		return false
	}
	
	//用户群列表加该群
	return AddGroup(conn, appid, uid, gid)
}

//删除群组
func (manager *Manager)DeleteGroup(appid int64, gid int64, owner int64) bool {
	g := manager.GetGroup(appid, gid)
	
	if g == nil {
		return true
	}
	
	if g.Owner != owner {
		return false
	}
	
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	//遍历群成员，解除关系
	uids := GetMembers(conn, appid, gid)
	
	for _, uid := range uids {
		RemoveGroup(conn, appid, int64(uid), gid)
	}
	//删除群信息
	Remove(conn, appid, gid)
	
	return true
}

//群主将人移出群
func (manager *Manager)RemoveFromGroup(appid int64, gid int64, owner int64, uid int64) bool {
	g := manager.GetGroup(appid, gid)
	
	if g == nil {
		return false
	}
	
	if g.Owner != owner {
		return false
	}
	
	return manager.QuitGroup(appid, gid, uid)
}

//普通成员退出群组
func (manager *Manager)QuitGroup(appid int64, gid int64, uid int64) bool {
	g := manager.GetGroup(appid, gid)
	if g == nil {
		return false
	}
	
	if g.Owner == uid {
		return false
	}
	
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	//解除跟群成员关系
	if !RemoveGroup(conn, appid, uid, gid) {
		return false
	}
	
	return RemoveMember(conn, appid, gid, uid)
}

//获取群成员列表
func (manager *Manager)GetGroupMembers(appid int64, gid int64) []*User {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	uids := GetMembers(conn, appid, gid)
	
	c := make([]*User, 0, 10)
	for _, uid := range uids {
		u := manager.GetUser(appid, int64(uid));
		
		if u == nil {
			continue
		}
		
		c = append(c, u)
	}
	
	return c
}

func (manager *Manager)GetGroupMemberUids(appid int64, gid int64) []int {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	uids := GetMembers(conn, appid, gid)
	
	return uids
}

//获取用户群列表
func (manager *Manager)GetUserGroups(appid int64, uid int64) []*Group {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	gids := GetGroups(conn, appid, uid)
	
	c := make([]*Group, 0, 10)
	for _, gid := range gids {
		u := manager.GetGroup(appid, int64(gid));
		
		if u == nil {
			continue
		}
		
		c = append(c, u)
	}
	
	return c
}

//获取用户token
func (manager *Manager)GetUserToken(appid int64, uid int64) (string, error) {
	user := manager.GetUser(appid, uid);
	if user == nil {
		return "", nil
	}
	
	return user.Token, nil
}

//设置用户token
func (manager *Manager)SetUserToken(appid int64, uid int64, token string) bool {
	user := manager.GetUser(appid, uid);
	if user == nil {
		return false
	}
	
	user.Token = token
	return manager.SaveUser(user.Appid, user.Uid, user.Username, user.Avatar, user.Token)
} 

//获取用户登录服务器节点列表
func (manager *Manager)GetUserLoginPoints(appid int64, uid int64) ([]*UserLoginPoint, error) {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	device_ids := GetLoginPoints(conn, appid, uid)
	if device_ids == nil {
		return nil, nil
	}
	
	points := make([]*UserLoginPoint, 0, 5)
	
	for _, device_id := range device_ids {
		point := GetLoginPoint(conn, appid, uid, device_id)
		points = append(points, point)
	}
	
	return points, nil
}

//设置用户设备服务器登录节点
func (manager *Manager)SetUserLoginPoint(appid int64, uid int64, device_id string, platform_id int8, login_srv string, login_time int64) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	point := &UserLoginPoint{
		Device_id : device_id,
		Platform_id : platform_id,
		Login_srv : login_srv,
		Login_time : login_time,
	}
	
	if !SetLoginPoint(conn, appid, uid, point) {
		return false
	}
	
	return AddLoginPoints(conn, appid, uid, device_id)
}

//删除设备登录节点
func (manager *Manager)RemoveUserLoginPoint(appid int64, uid int64, device_id string) bool {
	conn := manager.redis_pool.Get()
	defer conn.Close()
	
	return RemoveLoginPoint(conn, appid, uid, device_id)
}